<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>01_深拷贝和浅拷贝-引用赋值</title>
  <!-- 
  在JavaScript中，深拷贝和浅拷贝是处理对象和数组时的重要概念，理解它们的区别对于避免潜在的错误和实现正确的数据处理非常重要。
  浅拷贝（Shallow Copy）
  浅拷贝是指对对象的第一层属性进行复制。如果对象的属性是基本数据类型（如字符串、数字、布尔值等），那么这些属性会被复制到新对象中；如果属性是引用类型（如对象或数组），则会复制其引用，而不是复制其值。这意味着原对象和新对象中的引用类型属性指向同一个内存地址。

   浅拷贝的实现方式：
  1. Object.assign():
    const obj1 = { a: 1, b: { c: 2 } };
    const shallowCopy = Object.assign({}, obj1);
    shallowCopy.b.c = 3; // 修改浅拷贝的对象
    console.log(obj1.b.c); // 输出 3，原对象也被修改
  2. 扩展运算符:
    const obj1 = { a: 1, b: { c: 2 } };
    const shallowCopy = { ...obj1 };
    shallowCopy.b.c = 3; // 修改浅拷贝的对象
    console.log(obj1.b.c); // 输出 3，原对象也被修改
  深拷贝（Deep Copy）

  深拷贝是指对对象及其所有嵌套对象进行递归复制。深拷贝会创建一个新对象，并且新对象的所有属性都是原对象的独立副本，包括引用类型的属性。这意味着原对象和新对象之间没有任何引用关系，修改新对象不会影响原对象。

   深拷贝的实现方式：

  1. 使用 JSON 方法:
  const obj1 = { a: 1, b: { c: 2 } };
    const deepCopy = JSON.parse(JSON.stringify(obj1));
    deepCopy.b.c = 3; // 修改深拷贝的对象
    console.log(obj1.b.c); // 输出 2，原对象未被修改
  注意：这种方法有一些限制，例如无法复制函数、undefined、Symbol、RegExp等特殊对象。

  2. 使用递归函数:
    function deepClone(obj) {
        if (obj === null || typeof obj !== 'object') {
            return obj; // 基本数据类型直接返回
        }
        if (Array.isArray(obj)) {
            const arrCopy = [];
            for (let item of obj) {
                arrCopy.push(deepClone(item)); // 递归拷贝数组元素
            }
            return arrCopy;
        }
        const objCopy = {};
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                objCopy[key] = deepClone(obj[key]); // 递归拷贝对象属性
            }
        }
        return objCopy;
    }
  总结
  - 浅拷贝：只复制对象的第一层属性，引用类型属性仍然指向原对象的内存地址，修改会影响原对象。
  - 深拷贝：递归复制对象及其所有嵌套属性，创建一个完全独立的副本，修改不会影响原对象。
  -->
</head>
<body>

  <script>
    console.log(window.window === window);

    const obj = {
      name: '张三',
      age: 18,
      gender: '男',
      car: {
        name: '奔驰',
        price: 100,
      },
      running: function () {
        console.log('跑步');
      },
      [Symbol('abc')]: 'aaa'
    }

    // obj.info = obj

    // 1. 引用赋值
    const obj1 = obj
    obj1.name = '李四'
    console.log(obj.name); // 输出 '李四'
    console.log(obj1.name); // 输出 '李四'
    console.log(obj === obj1); // 输出 true，说明 obj 和 obj1 指向同一个对象

    // 2. 浅拷贝
    const obj2 = { ...obj }
    obj2.name = '王五'
    console.log(obj.name); // 输出 '张三'
    console.log(obj2.name); // 输出 '王五'
    console.log(obj === obj2); // 输出 false，说明 obj 和 obj2 是不同的对象

    const obj3 = Object.assign({}, obj)
    obj3.name = '赵六'
    console.log(obj.name); // 输出 '张三'
    console.log(obj3.name); // 输出 '赵六'
    console.log(obj === obj3); // 输出 false，说明 obj 和 obj3 是不同的对象

    // 3. 深拷贝
    // 3.1 JSON.parse(JSON.stringify(obj))
    // JSON.stringify(obj) 不能出现循环引用，否则会报错 obj.info = obj
    const obj4 = JSON.parse(JSON.stringify(obj))
    obj4.name = '钱七'
    console.log(obj.name); // 输出 '张三'
    console.log(obj4.name); // 输出 '钱七'
    console.log(obj === obj4); // 输出 false，说明 obj 和 obj4 是不同的对象
    
    // 3.2.自己编写一个深拷贝函数(第三方库)


  </script>
  
</body>
</html>